home *** CD-ROM | disk | FTP | other *** search
/ Aminet 38 / Aminet 38 (2000)(Schatztruhe)[!][Aug 2000].iso / Aminet / dev / misc / diskreader.lha / diskreader.asm < prev    next >
Encoding:
Assembly Source File  |  2000-05-11  |  10.3 KB  |  529 lines

  1. ; diskreader.asm - essential functionality for game disk installers.
  2. ; © 1998-2000 Kyzer/CSG
  3.  
  4. ; FILEMODE means that no output diskfile will be used, therefore WRITE is
  5. ; dropped - instead, SAVEF is used to write individual files
  6.     IFND    FILEMODE
  7. FILEMODE=0
  8.     ENDC
  9.  
  10. ; TRACKMODE means that all tracks are DOS tracks, so the user specifies
  11. ; the trackdisk-like device on the command line, and RAWREAD/RESYNC are 
  12. ; dropped
  13.     IFND    TRACKMODE
  14. TRACKMODE=0
  15.     ENDC
  16.  
  17. ; MESSAGES means that each track read will print out its number for the
  18. ; user to see.
  19.     IFND    MESSAGES
  20. MESSAGES=0
  21.     ENDC
  22.  
  23. ; NO_INCLUDES means that no system includes are neccessary to use diskreader
  24.     IFD    NO_INCLUDES
  25. IO_COMMAND=28            ; from devices/trackdisk.i
  26. IO_FLAGS=30
  27. IO_LENGTH=36
  28. IO_DATA=40
  29. IO_OFFSET=44
  30. IOTD_SIZE=56
  31. CMD_READ=2
  32. TD_MOTOR=9
  33. TD_RAWREAD=16
  34. IOTDB_INDEXSYNC=4
  35. MODE_NEWFILE=1006        ; from dos/dos.i
  36. ERROR_NOT_A_DOS_DISK=225
  37. _LVOOpen=-30            ; from dos/dos_lib.i
  38. _LVOClose=-36
  39. _LVOWrite=-48
  40. _LVOIoErr=-132
  41. _LVOPrintFault=-474
  42. _LVOReadArgs=-798
  43. _LVOFreeArgs=-858
  44. _LVOPutStr=-948
  45. _LVOVPrintf=-954
  46. _LVOCloseLibrary=-414        ; from exec/exec_lib.i
  47. _LVOOpenDevice=-444
  48. _LVOCloseDevice=-450
  49. _LVODoIO=-456
  50. _LVOOpenLibrary=-552
  51. _LVOCreateIORequest=-654
  52. _LVODeleteIORequest=-660
  53. _LVOCreateMsgPort=-666
  54. _LVODeleteMsgPort=-672
  55.     ELSE
  56.     include    devices/trackdisk.i
  57.     include    dos/dos.i
  58.     include    dos/dos_lib.i
  59.     include    exec/exec_lib.i
  60.     ENDC
  61.  
  62. DOSTRACKLEN=512*11
  63.  
  64. BUFFER    MACRO    ; buffername
  65. \1    equ    __trk
  66.     ENDM
  67.  
  68. FAILURE    MACRO    ; [reason]
  69.     IFEQ    NARG
  70.     suba.l    a0,a0
  71.     ELSE
  72.     lea    \1,a0
  73.     ENDC
  74.     bra    __fail
  75.     ENDM
  76.  
  77.     IFEQ    TRACKMODE
  78. RAWREAD    MACRO    ; track
  79.     lea    __trk,a0
  80.     move.l    \1,d0
  81.     bsr    __rawrd
  82.     ENDM
  83. RESYNC    MACRO    ; wordsync
  84.     lea    __trk,a0
  85.     move.l    \1,d0
  86.     bsr    __sync
  87.     ENDM
  88.     ENDC
  89. DOSREAD    MACRO    ; track
  90.     lea    __trk,a0
  91.     move.l    \1,d0
  92.     bsr    __dosrd
  93.     ENDM
  94.  
  95.     IFEQ    FILEMODE
  96. WRITE    MACRO    ; length, [offset]
  97.     IFEQ    NARG-2
  98.     lea    __trk,a0
  99.     add.l    \2,a0
  100.     ELSE
  101.     lea    __trk,a0
  102.     ENDC
  103.     move.l    \1,d0
  104.     bsr    __write
  105.     ENDM
  106. WRITEDOS MACRO    ; track
  107.     DOSREAD    \1
  108.     WRITE    #DOSTRACKLEN
  109.     ENDM
  110.  
  111.     ELSE
  112. SAVEF    MACRO    ; filename, buffer, length
  113.     lea    \1,a0
  114.     lea    \2,a1
  115.     move.l    \3,d0
  116.     bsr    __savef
  117.     ENDM
  118.     ENDC
  119.  
  120. ;------------------------------------
  121.  
  122. call    macro
  123.     jsr    _LVO\1(a6)
  124.     endm
  125.  
  126. initstk    macro    ; stack_symbol, stackreg
  127.     link    \2,#\1
  128.     move.l    sp,a0
  129. .clr\@    clr.w    (a0)+
  130.     cmp.l    a0,\2
  131.     bne.s    .clr\@
  132.     endm
  133.  
  134. stackf    MACRO    ; stack_symbol, stackelement_symbol, [size=4]
  135.     IFND    \1
  136. \1    set    0
  137.     ENDC
  138.     IFGE    NARG-3
  139. \1    set    \1-(\3)
  140.     ELSE
  141. \1    set    \1-4
  142.     ENDC
  143. \2    equ    \1
  144.     ENDM
  145.  
  146. ; create appropriate command line arguments based on FILEMODE/TRACKMODE
  147.     IFNE    FILEMODE
  148.     IFNE    TRACKMODE
  149.  
  150.     ; filemode on, trackmode on
  151.     stackf    stk, __unit
  152.     stackf    stk, __device
  153. __args=__device
  154. __nargs=2
  155. __tmpl    macro
  156.     dc.b    "DEVICE/A,UNIT/N/A",0
  157.     endm
  158.  
  159.     ELSE
  160.  
  161.     ; filemode on, trackmode off
  162.     stackf    stk, __unit
  163. __args=__unit
  164. __nargs=1
  165. __tmpl    macro
  166.     dc.b    "UNIT/N/A",0
  167.     endm
  168.  
  169.     ENDC
  170.     ELSE
  171.     IFNE    TRACKMODE
  172.  
  173.     ; filemode off, trackmode on
  174.     stackf    stk, __unit
  175.     stackf    stk, __device
  176.     stackf    stk, __output
  177. __args=__output
  178. __nargs=3
  179. __tmpl    macro
  180.     dc.b    "DISKFILE/A,DEVICE/A,UNIT/N/A",0
  181.     endm
  182.  
  183.     ELSE
  184.  
  185.     ; filemode off, trackmode off
  186.     stackf    stk, __unit
  187.     stackf    stk, __output
  188. __args=__output
  189. __nargs=2
  190. __tmpl    macro
  191.     dc.b    "DISKFILE/A,UNIT/N/A",0
  192.     endm
  193.  
  194.     ENDC
  195.     ENDC
  196.  
  197. ; other variables used
  198.  
  199.     stackf    stk, __rdargs    ; returned by ReadArgs()
  200.     stackf    stk, __diskport    ; replyport for diskio
  201.     stackf    stk, __diskio    ; IORequest to trackdisk.device
  202.     stackf    stk, __outfh    ; output filehandle (NULL in filemode)
  203.     stackf    stk, __initsp    ; initial (sp): move to sp then rts to quit
  204.     stackf    stk, __reason    ; ptr to textual reason for failure, or NULL
  205.     stackf    stk, __ioerr    ; a particular error code, overriding IoErr()
  206.     stackf    stk, execbase    ; exec.library
  207.     stackf    stk, dosbase    ; dos.library
  208.  
  209. ;------------------------------------
  210.  
  211.     section    diskreader,code
  212.     link    a5,#stk
  213.     move.l    4.w,a6
  214.     move.l    a6,execbase(a5)
  215.  
  216. ; no printable reason for failure, but start with errorcode
  217. ; incase we can't open DOS
  218.  
  219.     clr.l    __reason(a5)
  220.     clr.l    __ioerr(a5)
  221.     moveq    #100,d7
  222.  
  223. ; open dos.library
  224.     moveq    #37,d0
  225.     lea    __dosnm(pc),a1
  226.     call    OpenLibrary
  227.     move.l    d0,dosbase(a5)
  228.     beq    .nodos
  229.     move.l    d0,a6
  230.  
  231. ; read arguments on command line
  232.     lea    __templ(pc),a0
  233.     move.l    a0,d1
  234.     lea    __args(a5),a0
  235.     move.l    a0,d2
  236.     REPT    __nargs
  237.     clr.l    (a0)+
  238.     ENDR
  239.     moveq    #0,d3
  240.     call    ReadArgs
  241.     move.l    d0,__rdargs(a5)
  242.     beq    .noargs
  243.  
  244. ; create the output diskfile (unless FILEMODE)
  245.     IFEQ    FILEMODE
  246.     move.l    __output(a5),d1
  247.     move.l    #MODE_NEWFILE,d2
  248.     call    Open
  249.     move.l    d0,__outfh(a5)
  250.     beq.s    .nofile
  251.     ENDC
  252.  
  253. ; open trackdisk.device (or user-specified in TRACKMODE)
  254.     move.l    #ERROR_DEVICE_NOT_MOUNTED,__ioerr(a5)
  255.     move.l    execbase(a5),a6
  256.     call    CreateMsgPort
  257.     move.l    d0,__diskport(a5)
  258.     beq.s    .noport
  259.  
  260.     move.l    d0,a0
  261.     moveq    #IOTD_SIZE,d0
  262.     call    CreateIORequest
  263.     move.l    d0,__diskio(a5)
  264.     beq.s    .noio
  265.  
  266.     move.l    d0,a1
  267.     move.l    __unit(a5),a0
  268.     move.l    (a0),d0
  269.     IFNE    TRACKMODE
  270.     move.l    __device(a5),a0
  271.     ELSE
  272.     lea    __tdnm(pc),a0
  273.     ENDC
  274.     moveq    #0,d1
  275.     call    OpenDevice
  276.     tst.l    d0
  277.     bne.s    .nodev
  278.     clr.l    __ioerr(a5)
  279.  
  280. ;--------------------------------------
  281. ; call and return from the main 'slave'
  282.     bsr    __main
  283. ;--------------------------------------
  284.  
  285.  
  286. ; if messages mode, advance to new line for clarity
  287.     IFNE    MESSAGES
  288.     pea    10<<24    ; "\n\0\0\0"
  289.     move.l    sp,d1
  290.     move.l    dosbase(a5),a6
  291.     call    PutStr    ; print a newline
  292.     addq.l    #4,sp
  293.     ENDC
  294.  
  295. ; turn off disk motor
  296.     move.l    __diskio(a5),a1
  297.     move.w    #TD_MOTOR,IO_COMMAND(a1)
  298.     clr.l    IO_LENGTH(a1)
  299.     move.l    execbase(a5),a6
  300.     call    DoIO
  301.     
  302. ; close disk device
  303.     move.l    __diskio(a5),a1
  304.     call    CloseDevice
  305. .nodev    move.l    __diskio(a5),a0
  306.     call    DeleteIORequest
  307. .noio    move.l    __diskport(a5),a0
  308.     call    DeleteMsgPort
  309. .noport
  310.  
  311.     move.l    dosbase(a5),a6
  312.  
  313. ; close the output diskfile (if not FILEMODE)
  314.     IFEQ    FILEMODE
  315.     move.l    __outfh(a5),d1
  316.     call    Close
  317. .nofile
  318.     ENDC
  319.  
  320. ; free command-line arguments
  321.     move.l    __rdargs(a5),d1
  322.     call    FreeArgs
  323. .noargs
  324.  
  325. ; print error message if ioerror - this includes NOT_A_DOS_DISK
  326. ; if a printable reason exists, use that as the head of the printed
  327. ; error message.
  328.  
  329.     moveq    #0,d7         ; returncode = 0
  330.     move.l    __ioerr(a5),d1
  331.     bne.s    1$
  332.     call    IoErr
  333.     move.l    d0,d1
  334.     beq.s    2$
  335. 1$    moveq    #20,d7        ; returncode = 20
  336. 2$    move.l    __reason(a5),d2
  337.     call    PrintFault
  338.  
  339. ; close dos.library and go home
  340.     move.l    a6,a1
  341.     move.l    execbase(a5),a6
  342.     call    CloseLibrary
  343. .nodos    move.l    d7,d0
  344.     unlk    a5
  345.     rts
  346.  
  347.  
  348. ; internal routine to print out track number - D0 = track
  349.     IFNE    MESSAGES
  350. __prtrk    movem.l    d0-d2/a0,-(sp)
  351.     lea    __msg(pc),a0
  352.     move.l    a0,d1
  353.     move.l    sp,d2    ; points at D0 on the stack
  354.     move.l    dosbase(a5),a6
  355.     call    VPrintf
  356.     movem.l    (sp)+,d0-d2/a0
  357.     rts
  358.     ENDC
  359.  
  360. ; if TRACKMODE, then use a complete DOSREAD routine
  361.  
  362.     IFNE    TRACKMODE
  363. ;------------------------------------
  364. ; a0 = buffer, d0 = track
  365. __dosrd    move.l    a6,-(sp)
  366.     IFNE    MESSAGES
  367.     bsr.s    __prtrk        ; print track number in messages mode
  368.     ENDC
  369.     move.l    __diskio(a5),a1
  370.     move.w    #CMD_READ,IO_COMMAND(a1)
  371.     move.l    #DOSTRACKLEN,d1
  372.     mulu    d1,d0            ; convert D0=track to D0=offset
  373.     move.l    d1,IO_LENGTH(a1)    ; D1 = length
  374.  
  375.     move.l    a0,IO_DATA(a1)
  376.     move.l    d0,IO_OFFSET(a1)
  377.     move.l    execbase(a5),a6
  378.     call    DoIO            ; read disk part
  379.     lea    __ertrk(pc),a0        ; fail with "error reading track"
  380.     tst.l    d0            ; if DoIO fails
  381.     bne.s    __fail    
  382.     move.l    (sp)+,a6
  383.     rts
  384.     ELSE
  385.  
  386. ; if not TRACKMODE, merge the common parts of RAWREAD and DOSREAD
  387.  
  388. ;------------------------------------
  389. ; a0 = buffer, d0 = track
  390. __dosrd    move.l    a6,-(sp)
  391.     IFNE    MESSAGES
  392.     bsr.s    __prtrk
  393.     ENDC
  394.     move.l    __diskio(a5),a1
  395.     move.w    #CMD_READ,IO_COMMAND(a1)
  396.     move.l    #DOSTRACKLEN,d1
  397.     mulu    d1,d0            ; as above, D0 = offset, D1 = length
  398.     move.l    d1,IO_LENGTH(a1)
  399.     bra.s    __rdcom
  400.  
  401. ;------------------------------------
  402. ; a0 = buffer, d0 = track
  403. __rawrd    move.l    a6,-(sp)
  404.     IFNE    MESSAGES
  405.     bsr.s    __prtrk
  406.     ENDC
  407.     move.l    __diskio(a5),a1
  408.     move.w    #TD_RAWREAD,IO_COMMAND(a1)
  409.     move.b    #IOTDB_INDEXSYNC,IO_FLAGS(a1)    ; just for fun...
  410.     move.l    #$7ffe,IO_LENGTH(a1)    ; here length always is maximum
  411.  
  412. __rdcom    move.l    a0,IO_DATA(a1)
  413.     move.l    d0,IO_OFFSET(a1)
  414.     move.l    execbase(a5),a6
  415.     call    DoIO            ; error handling as above
  416.     lea    __ertrk(pc),a0
  417.     tst.l    d0
  418.     bne.s    __fail
  419.     move.l    (sp)+,a6
  420.     rts
  421.     ENDC
  422.  
  423. ; FAIL will always quit out of the 'slave' and return to the main
  424. ; routine, whatever the location on the stack
  425.  
  426. ;------------------------------------
  427. ; a0 = failure reason
  428. __fail    move.l    a0,d0
  429.     beq.s    .noreas
  430.     move.l    d0,__reason(a5)
  431.     move.l    #ERROR_NOT_A_DOS_DISK,__ioerr(a5)
  432. .noreas    move.l    __initsp(a5),sp
  433.     rts
  434.  
  435. ; in FILEMODE, there is a SAVEF which saves a whole file with its own name.
  436.  
  437.     IFNE    FILEMODE
  438. ;------------------------------------
  439. ; a0 = filename, a1 = buffer, d0 = length
  440. __savef    movem.l    d2-d4/a0/a6,-(sp)    ; careful! 12(sp)=a0
  441.     move.l    a0,d1
  442.     move.l    a1,d3    ; d3 = buffer
  443.     move.l    d0,d4    ; d4 = length
  444.     move.l    #MODE_NEWFILE,d2
  445.     move.l    dosbase(a5),a6
  446.     call    Open
  447.     move.l    d0,d1    ; d1 = filehandle
  448.     move.l    d3,d2    ; d2 = buffer
  449.     move.l    d4,d3    ; d3 = length
  450.     move.l    d0,d4    ; d4 = filehandle
  451.     beq.s    .fail
  452.     call    Write
  453.     move.l    d0,d3
  454.     move.l    d4,d1
  455.     call    Close
  456.     tst.l    d3
  457.     bmi.s    .fail
  458.     movem.l    (sp)+,d2-d4/a0/a6    ; careful! 12(sp)=a0
  459.     rts
  460. .fail    move.l    12(sp),__reason(a5)    ; get A0(name) from movem as reason
  461.     clr.l    __ioerr(a5)        ; return and use IoErr() as error
  462.     move.l    __initsp(a5),sp
  463.     rts
  464.  
  465.     ELSE
  466. ; off FILEMODE, you can only write to the diskfile
  467.  
  468. ;------------------------------------
  469. ; a0 = buffer, d0 = length
  470. __write    movem.l    d2-d3/a6,-(sp)
  471.     move.l    a0,d2
  472.     move.l    d0,d3
  473.     move.l    __outfh(a5),d1
  474.     move.l    dosbase(a5),a6
  475.     call    Write
  476.     tst.l    d0
  477.     bmi.s    __fail
  478.     movem.l    (sp)+,d2-d3/a6
  479.     rts
  480.     ENDC
  481.  
  482. ; RAW tracks need to be WORDSYNCed to be readable - this routine does that
  483.  
  484.     IFEQ    TRACKMODE
  485. ;------------------------------------
  486. ; a0 = buffer d0 = sync
  487. __sync    movem.l    d2-d3,-(sp)
  488.     move.l    a0,a1
  489.     move.w    #($7ffe/2)-1,d2        ; search entire trackbuffer
  490. .nxtwrd    moveq    #16-1,d3        ; find a BIT distance...
  491. .nxtbit    move.l    (a0),d1            ; and a BYTE distance..
  492.     lsr.l    d3,d1
  493.     cmp.w    d0,d1            ; ... for which we find the SYNCWORD
  494.     beq.s    .synced
  495.     dbra    d3,.nxtbit
  496.     addq.l    #2,a0
  497.     dbra    d2,.nxtwrd
  498.     lea    .err(pc),a0        ; searched through all 32k...
  499.     bra.s    __fail            ; ...no sync marker found
  500.  
  501. .synced    move.l    (a0),d1            ; match; now we shift all the remaining
  502.     addq.l    #2,a0            ; trackdata backwards by this BIT and
  503.     lsr.l    d3,d1            ; BYTE distance, so the first word in
  504.     move.w    d1,(a1)+        ; the trackbuffer is the SYNCWORD
  505.     dbra    d2,.synced
  506.     movem.l    (sp)+,d2-d3
  507.     rts
  508. .err    dc.b    "can't find sync mark",0
  509.     ENDC
  510.  
  511. __ertrk    dc.b    "error reading track",0
  512. __dosnm    dc.b    "dos.library",0
  513. __templ    __tmpl
  514.     IFEQ    TRACKMODE
  515. __tdnm    dc.b    "trackdisk.device",0
  516.     ENDC
  517.     IFNE    MESSAGES
  518. __msg    dc.b    "reading track %ld",13,0
  519.     ENDC
  520.     cnop    0,4
  521.  
  522.     ; create 32kb CHIP BSS hunk for trackbuffer
  523.     section    trackbuf,bss,chip
  524. __trk    ds.b    $7ffe
  525.  
  526.     ; return to main code section
  527.     section    diskreader,code
  528. __main    move.l    sp,__initsp(a5)
  529.